<?php


namespace app\api\service;


use app\lib\enum\OrdersStatusEnum;
use app\lib\exception\OrderException;
use app\lib\exception\TokenException;
use think\Exception;
use think\Log;
use wechatpay\base\WxPayJsApiPay;
use wechatpay\base\WxPayUnifiedOrder;
use wechatpay\WxPayApi;

class Pay
{
    private $ordersID;
    private $ordersCode;

    function __construct($ordersID)
    {
        if (!$ordersID) {
            throw new Exception('订单号不允许为空');
        }
        $this->ordersID = $ordersID;
    }

    // 处理支付
    public function pay()
    {
        // 订单合法性检测
        $this->checkOrdersValid();

        // 检测库存
        $ordersService = new Orders();
        $status = $ordersService->checkDishNum($this->ordersID);
        if (!$status['pass']) {
            return $status;
        }

        return $this->makeWxPreOrders($status['ordersPrice']);
    }

    // 微信预订单生成
    private function makeWxPreOrders($totalPrice)
    {
        // 获取openid
        $openid = BaseToken::getCurrentToken('openid');
        if (!$openid) {
            throw new TokenException();
        }

        // 统一下单
        $wxOrdersData = new WxPayUnifiedOrder();
        //订单号
        $wxOrdersData->SetOut_trade_no($this->ordersCode);
        // 类型
        $wxOrdersData->SetTrade_type('JSAPI');
        $wxOrdersData->SetTotal_fee($totalPrice * 100);
        $wxOrdersData->SetBody('食品食堂');
        $wxOrdersData->SetOpenid($openid);
        // 回调通知
        $wxOrdersData->SetNotify_url(config('secure.pay_back_url'));
        return $this->getPaySignature($wxOrdersData);
    }

    // 签名参数结果
    private function getPaySignature($wxOrdersData)
    {
        // 调用微信支付接口
        $wxOrders = WxPayApi::unifiedOrder($wxOrdersData);
        if ($wxOrders['return_code'] != 'SUCCESS' || $wxOrders['result_code'] != 'SUCCESS') {
            // 记录日志
            Log::record($wxOrders, 'error');
            Log::record('获取预支付订单失败', 'error');
        }
        // 获取prepay_id
        $this->recordPreOrders($wxOrders);

        $signature = $this->sign($wxOrders);
        return $signature;
    }

    // 微信签名
    private function sign($wxOrders)
    {
        $jsApiPayData = new WxPayJsApiPay();
        $jsApiPayData->SetAppid(config('wx.app_id'));
        $jsApiPayData->SetTimeStamp((string)time());
        // 随机字符串
        $rand = md5(time().mt_rand(0, 999));
        $jsApiPayData->SetNonceStr($rand);

        $jsApiPayData->SetPackage('prepay_id='.$wxOrders['prepay_id']);
        $jsApiPayData->SetSignType('md5');

        // 生成签名
        $sign = $jsApiPayData->MakeSign();
        // 转换成原始数值
        $rawValues = $jsApiPayData->GetValues();
        // 将签名传入
        $rawValues['paySign'] = $sign;

        // appId
        unset($rawValues['appId']);
        return $rawValues;
    }

    // 通过prepay_id向用户推送模板消息
    private function recordPreOrders($wxOrders)
    {
        \app\api\model\Orders::where('id', '=', $this->ordersID)
            ->update(['prepay_id'=>$wxOrders['prepay_id']]);
    }

    // 订单合法性检测
    private function checkOrdersValid()
    {
        // 检测订单号
        $orders = \app\api\model\Orders::where('id', '=', $this->ordersID)->find();
        if (!$orders) {
            throw new OrderException();
        }

        // 检测订单号和当前用户是否匹配
        if (!BaseToken::isValid($orders->openid)) {
            throw new TokenException([
                'msg' => '订单与用户不匹配',
                'errorCode' => 1003
            ]);
        }

        // 检测订单是否已支付
        if ($orders->orders_state != OrdersStatusEnum::unPaid) {
            throw new OrderException([
                'msg' => '订单已经支付过，请勿重复提交',
                'errorCode' => 7003,
                'code' => 400
            ]);
        }
        $this->ordersCode = $orders->orders_code;
        return true;
    }
}